﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.ComponentModel;
using NHibernate;
using Mindfor.Web.Data;

namespace Mindfor.Web
{
	/// <summary>
	///  Maps a browser request to a data object.
	///  Can map NHibernate entities throw Id fields.
	/// </summary>
	public class CmsModelBinder : DefaultModelBinder
	{
		/// <summary>
		/// Binds the specified property by using the specified controller context and
		/// binding context and the specified property descriptor.
		/// </summary>
		/// <param name="controllerContext">The context within which the controller operates. The context information
		/// includes the controller, HTTP content, request context, and route data.</param>
		/// <param name="bindingContext">The context within which the model is bound. The context includes information
		/// such as the model object, model name, model type, property filter, and value
		/// provider.</param>
		/// <param name="propertyDescriptor">Describes a property to be bound. The descriptor provides information such
		/// as the component type, property type, and property value. It also provides
		/// methods to get or set the property value.</param>
		protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
		{
			// process only id entity binding
			if (propertyDescriptor.PropertyType.IsSubclassOf(typeof(IdEntity)))
			{
				string key = (String.IsNullOrEmpty(bindingContext.ModelName) ? "" : bindingContext.ModelName + ".")
					+ propertyDescriptor.Name + ".Id";
				ValueProviderResult result = bindingContext.ValueProvider.GetValue(key);
				if (result != null)
				{
					int? id = null;
					try
					{
						id = (int)result.ConvertTo(typeof(int));
					}
					catch
					{
					}

					if (id.HasValue)
					{
						ISession data = CmsApplication.DataProvider.GetCurrentSession();
						if (data == null)
							throw new InvalidOperationException("Cannot get current session.");

						object entity = data.Get(propertyDescriptor.PropertyType, id);
						propertyDescriptor.SetValue(bindingContext.Model, entity);
					}
					return;
				}
			}
			
			// bind other properties
			base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
		}
	}
}
